package com.cman777.springc.web.aspect;


import com.cman777.springc.common.helper.JsonHelper;
import com.cman777.springc.common.helper.MapUtil;
import com.cman777.springc.web.holder.RequestInfoHolder;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author chenzhicong
 * @time 2019/11/9 18:02
 * @description
 */
@Log4j2
@Aspect
@Component
@Order(Integer.MIN_VALUE)
public class LogAspect {
    /**
     * 定义切面,controller包的所有方法
     */
    @Pointcut("execution(public * com..*.controller..*.*(..))")
    public void logger4Controller() {}
    /**
      * client包的所有方法（服务内部调用）
      */
    @Pointcut("execution(public * com..*.client..*.*(..))")
    public void logger4Client() {}

    /**
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("logger4Controller()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String className = proceedingJoinPoint.getTarget().getClass().getSimpleName();
        String methodName = proceedingJoinPoint.getSignature().getName();
        String methodInfo = className + "." + methodName;
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        /**
         * 遍历header
         */
        Map<String,String> headerMap = new HashMap<>(32);
        Enumeration<String> enumeration = request.getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String name = enumeration.nextElement();
            String value = request.getHeader(name);
            headerMap.put(name,value);
        }

        /**
         * 遍历parameter或body
         */
        Map<String, String> map = MapUtil.getStringMap(request.getParameterMap());
        String operatorId = map.get("operatorId");
        log.info(" header参数:{};query参数:{}", JsonHelper.toJsonStringQuietly(headerMap), JsonHelper.toJsonStringQuietly(map));
        String contentType = request.getContentType();
        //如果是json请求(避免上传打印字节流)
        if (StringUtils.isNotBlank(contentType) && contentType.contains("application/json")) {
            String body = RequestInfoHolder.getBody();
            log.info("body参数:{}",body);
            try {
                Map jsonMap = JsonHelper.toObject(body,HashMap.class);
                if (StringUtils.isBlank(operatorId)) {
                    operatorId = Optional.ofNullable(jsonMap.get("operatorId"))
                            .map(Object::toString).orElse(null);
                }

            } catch (Exception e) {
                log.debug("JackSon解析body中的字符串失败");
            }
        }
        //如果没有传操作人则默认设置一个
        if (StringUtils.isBlank(operatorId)) {
            operatorId = "anonymous";
        }
        RequestInfoHolder.setOperatorId(operatorId);

        Object result = proceedingJoinPoint.proceed();
        log.info("{}方法被调用,出参：{}",methodInfo,JsonHelper.toJsonStringQuietly(result));
        return result;
    }


}
